/**
 * @description 生成数组元素的所有排列（包含重复项）
 * @description 警告：这个函数的执行时间随着每个数组元素呈指数增长。超过 8 到 10 个条目可能会导致您的浏览器在尝试解决所有不同组合时挂起。
 * @param {*} arr
 * @returns
 */
const permutations = (arr) => {
  // 判断只有 1 或 2 个元素的数组
  if (arr.length <= 2) return arr.length === 2 ? [arr, [arr[1], arr[0]]] : arr;
  // Array.prototype.reduce() 对所有排列在一个阵列中结合起来
  return arr.reduce((acc, item, i) => 
    // item
    // 1
    // 33
    // 5
    // Array.prototype.concat() 连接起来
    acc.concat(
      // 递归
      // 使用Array.prototype.map()的元件与每个部分交换结合
      permutations([...arr.slice(0, i), ...arr.slice(i + 1)]).map((val) =>
        [item, ...val])
        // [item, ...val]
        // [1, 33, 5] [1, 5, 33]
        // [33, 1, 5] [33, 5, 1]
        // [5, 1, 33] [5, 33, 1]
    )
  ,
  []);
};

permutations([1, 33, 5]);
// [ [1, 33, 5], [1, 5, 33], [33, 1, 5], [33, 5, 1], [5, 1, 33], [5, 33, 1] ]
